home *** CD-ROM | disk | FTP | other *** search
- (c) 1990 S.Hawtin.
- Permission is granted to copy this file provided
- 1) It is not used for commercial gain
- 2) This notice is included in all copies
- 3) Altered copies are marked as such
-
-
- One complaint that is voiced about 'C' is that trivial programs are too
- large. This opinion is usually held by those who have "played with" 'C'
- and only every produced trivial programs, in this directory I explain how
- to make smaller 'C' programs, and what you lose by doing so.
-
- Before I can describe how to create small programs I must explain why
- the simplest 'C' program, which is
-
- main()
- {
- }
-
- takes so much space.
-
- The first thing to note is that every 'C' program consists of three
- parts, the startup code, the programmers routines, and the 'C' library.
- The startup code is a standard set of routines that are called when every
- 'C' program starts, these routines set up things so that the 'C' library
- will work and calls the users main() routine in a standard way. The 'C'
- library is a set of routines that the user may want to call, these range
- from the very well used routines such as printf() to the extremely obscure
- routines such as strpbrk().
-
- The 'C' library will only add code if one of the other two parts
- requires it, so for example the strstr() function is added to the
- application only if it is called from the startup, which it isn't, or the
- users code. For some routines the situation is more complicated, the
- fputs() routine, for example, calls the fputc() routine, so if the startup
- calls fputs() then both fputs() and fputc() are linked into the final
- executable program from the 'C' library.
-
- The normal 'C' startup code calls some routines in the 'C' library, on
- real applications this makes little difference to the size of the final
- code, because the users code probably calls all the routines that the
- startup uses anyway. On trivial applications the chances are that the
- routines the application calls are different from those that the startup
- uses. For example the startup uses fputs() if the application calls
- printf() then the final code must include both routines, even though they
- do almost the same job, so the final program will be larger. So if the
- hello world program is written as
-
- #include <stdio.h>
-
- main()
- {fputs("Hello world\a\n",stdout);
- }
-
- then the executable code will be smaller, the routines that the startup
- uses are
-
- atexit() CloseLibrary() exit()
- fclose() fflush() fputc()
- fputs() free() ltoa()
- malloc() OpenLibrary() strncpy()
- _exit() _main()
-
- so if you stick to this set you will reduce the size of your program.
-
- This is all to the good, however since the empty program is a few
- kilobytes long this is not the ultimate answer, we must reduce the size of
- the startup code.
-
- The startup code is the same for the vast majority of 'C' programs, the
- programmer has to work hard to use a different startup routine. This
- means that the startup must initialise the data structures for all the
- possible library routines that the program can call, for example the
- malloc() family of routines maintain a list of allocated memory chunks, so
- that they can be freed when the program exits, this list must be
- initialised just in case the program is going to call malloc(). There are
- quite a few lists and data structures that must be set up.
-
- The startup code is split over a number of routines, the "crt0.asm" file
- contains most of the low level routines, these call the higher level
- routines. The low level routines initialise the malloc() lists, the
- floating point support, the Amiga library support, the low level file
- handling, starting from the Workbench and the low level _exit() routine.
- The high level routines deal with the "FILE" structures, the exit() and
- atexit() routines, and the command line processing. Most of the space in
- the high level routines deals with the command line processing, this is an
- area that is often neglected, for example the command
-
- example "Arg one in quotes" two three
-
- has three arguments. Other languages, and even some 'C' compilers, will
- treat this as six arguments.
-
- So the reason why the empty program is so large is that it contains
- support for all the obscure 'C' routines you could have used, even if you
- don't. So the ultimate way to reduce the final size of your 'C' code is
- to take out the support for the routines you are not going to use, start
- with the "crt0.asm" file, and take out the calls that initialise the
- structures you don't want. This is what I have done in this directory, I
- have created "crt1.asm" a startup that sets up very little, and calls the
- routine _main().
-
- Of course if you want to use this trick to reduce the size of a program
- you would take the following steps,
-
- 1) Get the program working with the normal startup.
- 2) Change the main() routine from
-
- main(argc,argv)
- int argc;
- char **argv;
- {
- .
- .
- }
-
- remove all the FILE references and change the function to
-
- extern long _cmndlen;
- extern char *_cmndstr;
- extern long _fromWB;
-
- _main()
- {
- .
- .
- }
-
- 3) Get a local copy of "crt1.asm" and remove the bits you don't need.
-
- 4) Edit your Makefile to use the local "crt1.o" rather than "clibs:crt0.o".
-
- Once you have done all this you will learn a great deal about the guru, it
- really is simpler to live with the larger programs.
-